package com.settlement.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.settlement.system.common.constant.SystemConstants;
import com.settlement.system.common.enums.PlatFormEnum;
import com.settlement.system.common.util.DateUtils;
import com.settlement.system.common.util.NumberUtils;
import com.settlement.system.common.util.StringUtils;
import com.settlement.system.mapper.SysPlatformIdLinkMapper;
import com.settlement.system.mapper.TmOrderMapper;
import com.settlement.system.model.entity.SysMainSubNoConfig;
import com.settlement.system.model.entity.SysPlatformIdLink;
import com.settlement.system.model.entity.SysStore;
import com.settlement.system.model.entity.TmOrder;
import com.settlement.system.model.form.TmOrderForm;
import com.settlement.system.model.query.TmOrderQuery;
import com.settlement.system.model.vo.TmOrderImportVo;
import com.settlement.system.service.SnowflakeIdWorker;
import com.settlement.system.service.SysMainSubNoConfigService;
import com.settlement.system.service.SysStoreService;
import com.settlement.system.service.TmOrderService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 天猫平台订单 服务实现类
 * </p>
 *
 * @author huangrensen
 * @since 2024-05-09
 */
@Service
@RequiredArgsConstructor
public class TmOrderServiceImpl extends ServiceImpl<TmOrderMapper, TmOrder> implements TmOrderService {

    private final Logger logger = LoggerFactory.getLogger(TmOrderServiceImpl.class);
    private final SysStoreService storeService;

    private final SysMainSubNoConfigService sysMainSubNoConfigService;

    private final RedisTemplate redisTemplate;

    private final SysPlatformIdLinkMapper platformIdLinkMapper;

    private final SnowflakeIdWorker snowflakeIdWorker = SnowflakeIdWorker.getInstance();

    @Override
    public Page<TmOrder> getPage(TmOrderQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        // 拼接月份列表
        List<String> monthList = new ArrayList<>();
        String endMonthStr = queryParams.getEndMonth().replaceAll("-", "");
        LocalDate endMonth = LocalDate.parse(endMonthStr + "01", DateTimeFormatter.ofPattern("yyyyMMdd"));
        LocalDate startTime = LocalDate.parse(queryParams.getStartMonth().replaceAll("-", "") + "01", DateTimeFormatter.ofPattern(
                "yyyyMMdd"));
        // 获取已经生成的表名
        Object object = redisTemplate.opsForValue().get(SystemConstants.TM_ORDER_TABLE);
        List<String> tableNameList;
        if (object != null) {
            tableNameList = (List<String>) object;
        } else {
            tableNameList = this.baseMapper.getAllTable();
            // 添加缓存
            redisTemplate.opsForValue().set(SystemConstants.TM_ORDER_TABLE, tableNameList, 1, TimeUnit.HOURS);
        }
        // 循环追加月份
        while (!startTime.isAfter(endMonth)) {
            monthList.add(startTime.format(DateTimeFormatter.ofPattern("yyyyMM")));
            startTime = startTime.plusMonths(1);
        }
        // 根据月份判断数据库表是否存在
        List<String> existTableList = new ArrayList<>();
        String tableName;
        for (String month : monthList) {
            tableName = "tm_order_%s".formatted(month);
            if (tableNameList.contains(tableName)) {
                existTableList.add(tableName);
            }
        }
        Page<TmOrder> page = new Page<>(pageNum, pageSize);
        queryParams.setTableNameList(existTableList);
        // 查询数据
        if (existTableList.size() == 0) {
            return page;
        }
        // 查询数据
        Page<TmOrder> mapperPage = this.baseMapper.getPage(page, queryParams);
        SysStore sysStore;
        for (TmOrder record : mapperPage.getRecords()) {
            sysStore = storeService.getById(record.getStoreId());
            if (Objects.nonNull(sysStore)) {
                record.setStoreName(sysStore.getCommercePlatformStoreName());
            }
        }
        return mapperPage;
    }

    @Override
    public boolean saveTmOrder(TmOrderForm tmOrderForm) {
        TmOrder tmOrder = new TmOrder();
        BeanUtil.copyProperties(tmOrderForm, tmOrder);
        tmOrder.setCreateTime(null);
        return this.saveOrUpdate(tmOrder);
    }

    @Override
    public TmOrderForm getTmOrderFormData(Long id) {
        TmOrder tmOrder = this.getById(id);
        TmOrderForm tmOrderForm = new TmOrderForm();
        BeanUtil.copyProperties(tmOrder, tmOrderForm);
        return tmOrderForm;
    }

    @Override
    public boolean deleteTmOrder(String ids) {
        Assert.isTrue(StrUtil.isNotBlank(ids), "删除的数据为空");
        List<Long> idArray = Arrays.stream(ids.split(",")).map(Long::parseLong).collect(Collectors.toList());
        return this.removeByIds(idArray);
    }

    @Override
    public void importData(List<TmOrderImportVo> voList, String storeCode) {
        SysStore sysStore = storeService.getByCode(storeCode);
        // 主子单号配置关系
        SysMainSubNoConfig mainSubNoConfig = sysMainSubNoConfigService.getBaseMapper().selectOne(new LambdaQueryWrapper<SysMainSubNoConfig>().eq(SysMainSubNoConfig::getPreform, PlatFormEnum.T_MALL.getValue()));
        Assert.notNull(mainSubNoConfig, "主子单号配置不存在");
        Assert.isTrue(StringUtils.hasText(mainSubNoConfig.getSourcePreformMainNo()) && StringUtils.hasText(mainSubNoConfig.getSourcePreformSubNo()), "主子单号配置不存在");
        // 原始字段对应数据库字段
        Map<String, String> sourceColumnMap = TmOrderImportVo.getKeyMap();
        String sourcePreformSubNo;
        String sourcePreformMainNo;
        String columnEn;
        Field declaredField;
        String sourceColumnValue;
        SysPlatformIdLink platformIdLink;
        // 保存对应关系
        int year = LocalDate.now().getYear();
        String tableName = "sys_platform_id_link_%s".formatted(year);
        if (!StringUtils.hasText(platformIdLinkMapper.existTable(tableName))) {
            platformIdLinkMapper.createTable(tableName);
        }
        List<String> billMonthList = voList.stream().map(TmOrderImportVo::getBillMonth).distinct().toList();
        // 创建表
        for (String bMonth : billMonthList) {
            if (!StringUtils.hasText(this.baseMapper.existTable("tm_order_%s".formatted(bMonth)))) {
                this.baseMapper.createTable("tm_order_%s".formatted(bMonth));
            }
        }
        redisTemplate.delete(SystemConstants.TM_ORDER_TABLE);
        // 循环创建
        for (TmOrderImportVo importVo : voList) {
            TmOrder tmOrder = new TmOrder();
            BeanUtil.copyProperties(importVo, tmOrder, TmOrderImportVo.ignoreFields);
            tmOrder.setOrderCreateTime(DateUtils.convertStringToLocalDateTime(importVo.getOrderCreateTime()));
            tmOrder.setOrderPayTime(DateUtils.convertStringToLocalDateTime(importVo.getOrderPayTime()));
            tmOrder.setSendTime(DateUtils.convertStringToLocalDateTime(importVo.getSendTime()));
            tmOrder.setQty(NumberUtils.convertInteger(importVo.getQty()));
            tmOrder.setPrice(NumberUtils.convertBigDecimal(importVo.getPrice()));
            tmOrder.setTotalAmount(NumberUtils.convertBigDecimal(importVo.getTotalAmount()));
            tmOrder.setActTotalAmount(NumberUtils.convertBigDecimal(importVo.getActTotalAmount()));
            tmOrder.setStoreId(sysStore.getId());
            tmOrder.setTableName("tm_order_%s".formatted(importVo.getBillMonth()));
            tmOrder.setId(snowflakeIdWorker.nextId(importVo.getBillMonth()));
            tmOrder.cutString();
            this.baseMapper.insertData(tmOrder);
            platformIdLink = new SysPlatformIdLink();
            platformIdLink.setPlatfrom(PlatFormEnum.TM_ORDER.getValue());
            platformIdLink.setTableId(tmOrder.getId());
            // 通过主子单号配置，获取到原字段的值
            sourcePreformMainNo = mainSubNoConfig.getSourcePreformMainNo();
            sourcePreformSubNo = mainSubNoConfig.getSourcePreformSubNo();
            columnEn = sourceColumnMap.get(sourcePreformMainNo);
            // 通过反射获取原字段的值
            try {
                declaredField = tmOrder.getClass().getDeclaredField(columnEn);
                declaredField.setAccessible(true);
                sourceColumnValue = declaredField.get(tmOrder).toString();
                platformIdLink.setMainNo(sourceColumnValue);
            } catch (Exception e) {
                logger.error("获取反射属性失败：" + e.getMessage());
            }
            columnEn = sourceColumnMap.get(sourcePreformSubNo);
            try {
                declaredField = tmOrder.getClass().getDeclaredField(columnEn);
                declaredField.setAccessible(true);
                sourceColumnValue = declaredField.get(tmOrder).toString();
                platformIdLink.setSubNo(sourceColumnValue);
            } catch (Exception e) {
                logger.error("获取反射属性失败：" + e.getMessage());
            }
            try {
                platformIdLink.setTableName(tableName);
                platformIdLinkMapper.insertData(platformIdLink);
            } catch (Exception e) {
                logger.error("保存对应关系失败：" + e.getMessage());
            }
        }
    }

    @Override
    public List<TmOrderImportVo> findByIds(String idsStr) {
        if (StrUtil.isBlank(idsStr)) {
            return new ArrayList<>();
        }
        List<Long> ids = Arrays.stream(idsStr.split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<TmOrder> tmOrderList = this.getBaseMapper().selectBatchIds(ids);
        List<TmOrderImportVo> voList = new ArrayList<>();
        for (TmOrder tmOrder : tmOrderList) {
            TmOrderImportVo vo = new TmOrderImportVo();
            BeanUtil.copyProperties(tmOrder, vo);
            voList.add(vo);
        }
        return voList;
    }
}
